local Lang = require("common.Lang")
local HtmlUtil = require("common.HtmlUtil")
local Msg = require("core.Msg")
local Obj = require("core.Obj")
local ObjHuman = require("core.ObjHuman")
local Timer = require("core.Timer")
local Map = require("core.Map")
local RoleDefine = require("role.RoleDefine")
local Status = require("scene.Status")
local MapExcel = require("excel.Map")
local ExcelMonsterConf = require("excel.Monster")
local MonsterAttr = require("monster.MonsterAttr")
local MonsterAi = require("monster.MonsterAi")
local CombatCalc = require("skill.CombatCalc")
local RoleFFI = require("role.RoleFFI")
local Broadcast = require("broadcast.Broadcast")
local SkillConfig = require("excel.Skill").Skill
local Utility = require("excel.Skill").Utility
local Buffer  = require("buffer.Buffer")
local BufferNotify = require("buffer.Notify")
local DropLogic = require("monster.DropLogic")
local ExpLogic  = require("monster.ExpLogic")
local Copy = require("copy.CopyL")
local CopyCallback = require('copy.CallbackL')
local TaskCallbacks = require("task.TaskCallbacks")
local EffectLogic = require("scene.EffectLogic")
local BeginStory = require("scene.BeginStory")
local WildBossLogicL = require("wildboss.WildBossLogicL")
local CopyDefine = require("copy.Define")
local ArmyRiotLogicL = require("activity.armyRiot.ArmyRiotLogicL")
local OfflinePkDefine = require("offlinepk.Define")
local RoleDefine = require("role.RoleDefine")
local Grid = require("bag.Grid")
local ItemDefine = require("bag.ItemDefine")
local OfficialLogic = require("official.OfficialLogic")

local HP_MAX = RoleDefine.HP_MAX
local ATK = RoleDefine.ATK
local DEF = RoleDefine.DEF

local CAMPS = {
    isolate = 0,
    enemy	= 1,
    friend	= 2
}

enter_scene_list = enter_scene_list or {}
enter_scene_list_len = enter_scene_list_len or 0
MONSTERCORPSE_LIST = MONSTERCORPSE_LIST or {}

function create(monster_id, dyAttr)
    if not monster_id then
        assert()
    end
    local cf = ExcelMonsterConf.monster[monster_id]
    if not cf then
        assert(nil, monster_id)
    end
    local monster = {}
    monster.monster_id = monster_id
    monster.hp = cf.hp_max * cf.hp_init_p / 100
    monster.speed = cf.speed_alert
    monster.base_speed = cf.speed_alert
    monster.buf={}
    monster.bufLen = 0
    monster.attr = {}
    monster.bufAttr = {}
    monster.status = Status.HUMAN_STATUS_NORMAL	-- 状态
    monster.path_len = 0

    monster.radius		=cf.bodyRadius
    monster.can_hit		= getValueByMonsterType(monster, "can_hit")
    monster.camps		= CAMPS[cf.camps] and CAMPS[cf.camps]+0 or 0		-- 阵营

    monster.maxHurt = ExcelMonsterConf.monster[monster.monster_id].maxHurt
    
    monster.monsterType = ExcelMonsterConf.monster[monster.monster_id].monster_type
    MonsterAi.init_ai_data(monster)

    CombatCalc.initAttr(monster)
    Obj.create(monster, Obj.TYPE_MONSTER)

    ----------------------------------------------------
    --以下开始处理怪物动态属性，一般用于成长相关
    ----------------------------------------------------
    local dyAttr = nil
    local nDyMonsterData = MonsterAttr.getDyMonsterData(monster_id)
    if nDyMonsterData then
        local lvDownData = ExcelMonsterConf.monster[monster_id].dynamic_lvdown
        --这里加3600 一小时是为了避免误差的问题，增加几分钟也可
        local noKillDay = math.floor(nDyMonsterData.lastKillTime and math.abs((os.time() - ((nDyMonsterData.lastKillTime or 0) + 3600))) / 86400)
        local noKillDayLv = math.floor(noKillDay / lvDownData)
        local nSrcLv = nDyMonsterData.lv or 0
        local nBossLv = nSrcLv

        nDecLv = (nSrcLv - noKillDayLv) < 0 and 0 or (nSrcLv - noKillDayLv)
        if nDecLv ~= nSrcLv then
            nDyMonsterData.killCount = 0
            nDyMonsterData.lastKillTime = os.time()
            nDyMonsterData.lv = nDecLv
            nBossLv = nDecLv
            MonsterAttr.update(nDyMonsterData)
        end

        print("create monster boss lv is ", nBossLv)
        dyAttr = {}
        local dynamicHpRate = ExcelMonsterConf.monster[monster_id].dynamic_hp
        local dynamicAtkRate = ExcelMonsterConf.monster[monster_id].dynamic_atk
        local dynamicDefRate = ExcelMonsterConf.monster[monster_id].dynamic_def
        dyAttr[HP_MAX] = {1, nBossLv * (dynamicHpRate / 100)}
        dyAttr[ATK] = {1, nBossLv * (dynamicAtkRate / 100 )}
        dyAttr[DEF] = {1, nBossLv * (dynamicDefRate / 100)}
    end

    ----------------------------------------------------
    --以上开始处理怪物动态属性，一般用于成长相关
    ----------------------------------------------------

    doCalc(monster, dyAttr)
    if dyAttr then
        monster.hp = getHpMax(monster)
    end
    for _, v in ipairs(getValueByMonsterType(monster, "init_buf")) do
        Buffer.add(v, monster, monster)
    end
    return monster
end

-- 克隆分身
function clone(monster_id,owner)
    local monster = create(monster_id)
    if owner.obj_type == Obj.TYPE_HUMAN then
        monster.isCloneHuman = true
        monster.body, monster.weapon, monster.weaponEffect,monster.pifeng, monster.horse, monster.stone,monster.weapon2,monster.weapon2Effect = Obj.getBodyInfo(owner)
        monster.head = owner.db.head
    end

    return monster
end

function destroy(monster)
    monster.die = 1
    Buffer.destroy(monster)
    Obj.destroy(monster)
    local nSceneID = monster.scene_id
    if nSceneID and nSceneID > 0 and MONSTERCORPSE_LIST[nSceneID] and MONSTERCORPSE_LIST[nSceneID][monster.id] then
        MONSTERCORPSE_LIST[nSceneID][monster.id] = nil
        local nSendClearMsg = Msg.gc.GC_MONSTERCORPSE_REWARDCLEAR 
        nSendClearMsg.monster_id = monster.id
        if Obj.scenes[monster.scene_id] then
            for k, v in pairs(Obj.scenes[nSceneID]) do
                if v.obj_type == Obj.TYPE_HUMAN then
                    Msg.send(nSendClearMsg, v.fd)
                end
            end
        end
    end
end

function enterScene(monster, scene_id, x, y)
    local cf = ExcelMonsterConf.monster[monster.monster_id]
    local body_id = cf.born_effect_id
    if 0 < body_id then
        local mm = Msg.gc.GC_SHOW_DISPLAY
        mm.body_id = body_id
        mm.x = x
        mm.y = y
        mm.effectConfig = EffectLogic.getConfig(body_id)
        Obj.sendArea(mm, scene_id, x, y)
    end
    monster.born_x = x
    monster.born_y = y
    if 0 < cf.born_after_msec then
        monster.hide = 1
        enter_scene_list_len = enter_scene_list_len + 1
        enter_scene_list[enter_scene_list_len] = monster.id
    end
    Obj.enterScene(monster, scene_id, x, y, getValueByMonsterType(monster, "is_fly") == 1)
end

local function del_from_enter_scene_list(i)
    enter_scene_list[i] = enter_scene_list[enter_scene_list_len]
    enter_scene_list_len = enter_scene_list_len - 1
end

function time_enter_scene_list(now)
    local cf = ExcelMonsterConf.monster
    local objs = Obj.objs
    local sendArea = Obj.sendArea
    local mm = Msg.gc.GC_BEFORE_OBJ_APPEAR
    for i = enter_scene_list_len, 1, -1 do
        local id = enter_scene_list[i]
        local monster = objs[id]
        if monster and monster.monster_id and monster.hide then
            local cf = cf[monster.monster_id]
            if cf.born_after_msec < now - monster.uid then
                monster.hide = nil
                local scene_id = monster.scene_id
                local x = monster.x
                local y = monster.y
                local show_after_born = cf.show_after_born
                if 0 < show_after_born then
                    mm.obj_id = id
                    mm.cmd = show_after_born
                    sendArea(mm, scene_id, x, y)
                    monster.wake_up_time = Timer.now + cf.borntime
                end
                sendArea(getObjAdd(monster), scene_id, x, y)
                del_from_enter_scene_list(i)
            end
        else
            del_from_enter_scene_list(i)
        end
    end
end

function getExp(monster)
    return ExcelMonsterConf.monster[monster.monster_id].exp
end

function getHp(monster)
    return monster.hp
end

function getHpMax(monster)
    return monster.attr[RoleDefine.HP_MAX]
end

function setStiff(monster, hp_del)
    if monster.obj_type ~= Obj.TYPE_MONSTER then
        return
    end
    if not monster.attacker_id then
        return
    end
    if monster.walk_sleep then
        return
    end
    local monster_type = ExcelMonsterConf.monster[monster.monster_id].monster_type
    local cf = ExcelMonsterConf.monster_type[monster_type]
    if hp_del / getHpMax(monster) * 100 < cf.stiff_hp_percent then
        return
    end
    if not monster.stiff_time or cf.stiff_protect <= Timer.now - monster.stiff_time then
        monster.wake_up_time = Timer.now + cf.stiff
        monster.stiff_time = Timer.now + cf.stiff
        Obj.stop(monster)
    end
    --    if not monster.wake_up_time or cf.stiff_protect <= Timer.now - monster.wake_up_time then
    --        monster.wake_up_time = Timer.now + cf.stiff
    --        print("setStiff:", monster.wake_up_time)
    --        Obj.stop(monster)
    --    end
end

function onDie(monster,attacker, utilityConfig, hurt_mul, isQuake, notDyUp)
    monster.dieTime = Timer.now
    Obj.stop(monster)
    DropLogic.onMonsterDie(monster, attacker)

    ----------------------------------------------------
    --以下开始处理怪物动态属性，一般用于成长相关
    ----------------------------------------------------
    if not notDyUp then
        local lvUpData = ExcelMonsterConf.monster[monster.monster_id].dynamic_lvup
        if lvUpData and lvUpData[1] then
            local nDyMonsterData = MonsterAttr.getDyMonsterData(monster.monster_id) or {lv = 0, killCount = 0, lastKillTime = 0, monsterID = monster.monster_id, lastHitName = nil, lastHitUuid = nil}
            nDyMonsterData.lastHitName = attacker.name
            nDyMonsterData.lastHitUuid = attacker.uuid
            nDyMonsterData.killCount = nDyMonsterData.killCount and nDyMonsterData.killCount + 1 or 0
            nDyMonsterData.lastKillTime = os.time()
            nDyMonsterData.lv = nDyMonsterData.lv or 0

            local nAddLv = math.floor(nDyMonsterData.killCount / lvUpData[1]) >= 1 and 1 or 0
            if nAddLv >= 1 then
                nDyMonsterData.killCount = 0
            end
            nDyMonsterData.lv = (nDyMonsterData.lv + nAddLv) > (lvUpData[2] or 0) and (lvUpData[2] or 0) or (nDyMonsterData.lv + nAddLv)
            print("end monster boss lv is ", nDyMonsterData.lv)
            MonsterAttr.update(nDyMonsterData)
        end
    end
    ----------------------------------------------------
    --以上开始处理怪物动态属性，一般用于成长相关
    ----------------------------------------------------

    ArmyRiotLogicL.onMonsterDie(monster)
    if 0 < ExcelMonsterConf.monster[monster.monster_id].die_remain then
        Obj.sendGCObjDie(monster, attacker, utilityConfig, hurt_mul, isQuake)
    end
    local sumExp = ExpLogic.calc(monster)
    Buffer.onDie(monster)
    -- 任务里面对杀怪计数有两种方式 一种是攻击过就算 一种是和队友共享 但是外部不知道 所以要这两种都传给task里面去判断
    local callbackHuman = {}
    if monster.enemy_list then
        for human_uuid in pairs(monster.enemy_list) do  -- 获得攻击过这个怪物的玩家
            local member = ObjHuman.onlineUuid[human_uuid]
            if member then callbackHuman[member] = 1 end
        end
    end
    local atkerOwner = Obj.getOwner(attacker) or attacker


    if atkerOwner and atkerOwner.obj_type == Obj.TYPE_HUMAN then
        -- 获得杀死这个怪物的玩家及其队友
        if atkerOwner.db.teamUuidLen == 0 then
            callbackHuman[atkerOwner] = 0
        else
            for i = 1, atkerOwner.db.teamUuidLen do
                local memberUuid = RoleFFI.ffi_string(atkerOwner.db.teamUuid[i - 1].uuid)
                local member = ObjHuman.onlineUuid[memberUuid]
                if member and member.scene_id == monster.scene_id then
                    local dx = member.x - monster.x
                    local dy = member.y - monster.y
                    if member == atkerOwner or (-Obj.GRID_WIDTH < dx and dx < Obj.GRID_WIDTH and -Obj.GRID_HEIGHT < dy and dy < Obj.GRID_HEIGHT) then
                        callbackHuman[member] = 0
                    end
                end
            end
        end
        OfficialLogic.checkOneCondition(atkerOwner, "killMonster", monster.monster_id)
    end
    for human, killType in pairs(callbackHuman) do
        TaskCallbacks.taskMonsterDieCB(human, killType, monster, monster.monster_id)
    end

    if Copy.isCopyBySceneID(monster.scene_id) then
        CopyCallback.onMonsterDieCB(attacker, monster, monster.monster_id, sumExp)
    end

    if monster.monsterType == 6 then
        WildBossLogicL.onDie(attacker)
    end

    if monster.monsterType == 136 then
        local firstHitUuid = monster.firstHitUuid
        if firstHitUuid then
            local firstHitPlayer = ObjHuman.onlineUuid[firstHitUuid]
            local nMapID = Map.scene_id_to_map_id[monster.scene_id]
            if firstHitPlayer and nMapID and MapExcel.scene[nMapID] then
                local mapName = MapExcel.scene[nMapID].name
                Broadcast.sendBroadcast2World(Lang.UP + Lang.GROSSIP,string.format(Lang.MONSTER_KILL_TIP,HtmlUtil.fontName(firstHitPlayer.name, firstHitPlayer._id),HtmlUtil.font(mapName,"#00ff00")))
            end
        end
    end

    if ExcelMonsterConf.monster[monster.monster_id].canCorpseReward == 1 then
        local nSceneID = monster.scene_id
        if nSceneID and nSceneID > 0 then
            MONSTERCORPSE_LIST[nSceneID] = MONSTERCORPSE_LIST[nSceneID] or {}
            MONSTERCORPSE_LIST[nSceneID][monster.id] = {}
            sendMonsterCorpseList(nSceneID)
        end
    end
end

function getBuf(monster)
    return monster.buf,monster.bufLen
end

function setBufLen(monster, len)
    monster.bufLen = len
end

function getObjAdd(monster)
    local monster_type = ExcelMonsterConf.monster[monster.monster_id].monster_type
    local cf = ExcelMonsterConf.monster[monster.monster_id]
    local monster_type_cf = ExcelMonsterConf.monster_type[monster_type]

    --是否克隆
    local mm
    if false and monster.isCloneHuman then
        mm = Msg.gc.GC_ADD_MONSTER_CLONE
        mm.head = monster.head
        Status.makeViewInfo(mm.viewInfo,0,monster.body, monster.weapon, monster.weaponEffect,monster.pifeng, monster.horse, monster.stone, monster.weapon2, monster.weapon2Effect)
    else
        mm = Msg.gc.GC_ADD_MONSTER
        Status.makeViewInfo(mm.viewInfo, 0, Obj.getBodyInfo(monster))        
        mm.body_scale = cf.body_scale
        mm.body_height = cf.body_height
        mm.bindTask1 = cf.bindTask1
        mm.bindTask2 = cf.bindTask2
        mm.is_sp_cg = cf.sp_cg[1] and 1 or 0
        mm.firstHitUuid = monster.firstHitUuid or ""
        if monster.du_tiao_end_time and Timer.now < monster.du_tiao_end_time then
            mm.du_tiao_msec = monster.du_tiao_end_time - Timer.now
        else
            mm.du_tiao_msec = 0
        end
        if cf.drop_type ~= 1 and cf.drop_type ~= 2 then
            mm.firstHitUuid = ""
        end
        mm.drop_type = cf.drop_type
        mm.isSky = monster_type_cf.isSky
    end
    mm.type = monster_type_cf.type
    mm.obj_id = monster.id
    mm.name = getName(monster)
    mm.monsterType = monster_type
    mm.x = monster.x
    mm.y = monster.y
    mm.status = monster.status
    mm.radius = Obj.getRadius(monster)
    mm.speed = monster.speed
    mm.dir = monster.dir or monster_type_cf.dir[math.random(1, #monster_type_cf.dir)]
    mm.points[0] = monster.path_len * 2
    mm.rand_ai_name = monster.familyName or ""
    mm.can_select = monster_type_cf.can_select
    mm.solar_id = monster_type_cf.solar_id
    mm.solar_pos = monster_type_cf.solar_pos
    mm.solar_config = EffectLogic.getConfig(monster_type_cf.solar_id)
    mm.monster_id = monster.monster_id
    mm.show_name = monster_type_cf.show_name
    mm.hp = getHp(monster)
    mm.hpMax = getHpMax(monster)
    mm.hp_cnt = monster_type_cf.hp_cnt
    mm.lv = getLv(monster)
    mm.combatSide = monster.camps
    mm.canBlood = cf.can_blood

    local owner = Obj.getOwner(monster)
    mm.owner_uuid = owner and owner.db and owner._id or ""
    mm.z = monster.z or cf.z

    for i = 1, monster.path_len do
        local j = monster.path_len + 1 - i
        mm.points[2 * i - 1] = monster.path[2 * j - 1]
        mm.points[2 * i] = monster.path[2 * j]
    end
    mm.name_color = monster_type_cf.name_color
    BufferNotify.setBufferInfo(monster, mm.bufInfo)
    --	Status.sendViewStatus(monster,nil,true)

    return mm
end

function setHp(monster, hp)
    hp = math.floor(hp)
    hp = math.max(0, hp)
    hp = math.min(hp, getHpMax(monster))
    monster.hp = hp
end

function getName(monster)
    if monster.name then
        return monster.name
    else
        return ExcelMonsterConf.monster[monster.monster_id].name
    end
end

function getConfigName(monster)
    return ExcelMonsterConf.monster[monster.monster_id].name
end

function getLv(monster)
    if monster.lv then
        return monster.lv
    end
    return ExcelMonsterConf.monster[monster.monster_id].lv
end

function get_conf(monster)
    return ExcelMonsterConf.monster[monster.monster_id]
end

function getRadius(monster)
    return 	monster.radius
end

function doCalc(monster, dyAttr)
    MonsterAttr.doCalc(monster, dyAttr)
    Obj.setSpeed(monster,monster.attr[RoleDefine.SPEED])
end

--属性逻辑
function getAttr(monster, key)
    return monster.attr[key] or 0
end

function onBeHit(attacker,monster,hp_del)
    setStiff(monster, hp_del)
    monster.be_attacked_id = attacker.id

    -- exp
    -- drop item
    if attacker.obj_type == Obj.TYPE_HUMAN then
        monster.enemy_list = monster.enemy_list or {}
        if not monster.enemy_list[attacker._id] then
            monster.enemy_list[attacker._id] ={hurt = hp_del, time = os.time()}
        else
            monster.enemy_list[attacker._id].hurt = monster.enemy_list[attacker._id].hurt + hp_del
            monster.enemy_list[attacker._id].time = os.time()
        end
        if monster.firstHitTime and monster.firstHitUuid ~= attacker._id and monster.firstHitTime + 10000 < Timer.now then
            monster.firstHitUuid = nil --如果10s不再攻击，切换成其它人
        end
        local firstHitUuid_old = monster.firstHitUuid
        if not monster.firstHitUuid then
            monster.firstHitUuid = attacker._id
            monster.firstHitName = attacker.name
            monster.firstHitTime = Timer.now
        elseif monster.firstHitUuid ~= attacker._id then
            local human = ObjHuman.onlineUuid[monster.firstHitUuid]
            if not (human and 0 < human.db.hp and Obj.canSeeEachOther(human, monster)) then
                monster.firstHitUuid = attacker._id
                monster.firstHitName = attacker.name
                monster.firstHitTime = Timer.now
            end
        else
            monster.firstHitTime = Timer.now
        end
        if monster.firstHitUuid ~= firstHitUuid_old then
            if monster.monsterType == 6 then
                WildBossLogicL.onSendFirstHitData(attacker, true)
            else
                local t = ExcelMonsterConf.monster[monster.monster_id].drop_type
                if t == 1 or t == 2 then
                    local mm = Msg.gc.GC_CHANGE_FIRST_HIT_UUID
                    mm.obj_id = monster.id
                    mm.firstHitUuid = monster.firstHitUuid
                    mm.firstHitName = monster.firstHitName
                    mm.show = 0
                    Obj.sendArea(mm, monster.scene_id, monster.x, monster.y)
                end
            end
        end
        --if monster.monsterType == 3 then
        --    WorldBossLogicFL.onBeHit(attacker, hp_del)
        --end
        if Copy.isCopyBySceneID(monster.scene_id) then
            CopyCallback.onMonsterBeHitCB(attacker, monster, monster.monster_id, hp_del)
        end
    end
end

--形象
function getBodyInfo(monster)
    if monster.isCloneHuman then
        return monster.body, monster.weapon, monster.weaponEffect,monster.pifeng, monster.horse, monster.stone,monster.weapon2,monster.weapon2Efect,0,0,0
    end
    local cf = ExcelMonsterConf.monster[monster.monster_id]

    local weaponID = cf.weapon[1] or 0
    local weaponEffect = 0
    local weaponID2 = cf.weapon[2] or 0
    local pifengID = 0
    local body = cf.body_id
    local bodyColor = cf.color
    local horse = cf.horse
    local bone = cf.bone_id
    if monster.monster_id == BeginStory.BEGIN_STORY_MONSTER_ZHAOYUN_ID then
        weaponID = 2
        pifengID = 1
        weaponEffect = 800005
    elseif monster.monster_id == CopyDefine.OFFLINE_PK_BOSS_ID1 and monster.offlinepkRank then
        body = OfflinePkDefine.getMasterViewInfo(monster.offlinepkRank)
        horse = 0
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB1_ID1 and monster.monster_id <= CopyDefine.WUSHUANG_JOB1_ID2 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB1_ID1) * 10
        bone = 1
        weaponID = 3
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB1_ID3 and monster.monster_id <= CopyDefine.WUSHUANG_JOB1_ID4 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB1_ID3) * 10
        bone = 1
        weaponID = 3
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB1_ID5 and monster.monster_id <= CopyDefine.WUSHUANG_JOB1_ID6 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB1_ID5) * 10
        bone = 1
        weaponID = 3
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB2_ID1 and monster.monster_id <= CopyDefine.WUSHUANG_JOB2_ID2 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB2_ID1) * 10
        bone = 3
        weaponID = 10
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB2_ID3 and monster.monster_id <= CopyDefine.WUSHUANG_JOB2_ID4 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB2_ID3) * 10
        bone = 3
        weaponID = 10
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB2_ID5 and monster.monster_id <= CopyDefine.WUSHUANG_JOB2_ID6 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB2_ID5) * 10
        bone = 3
        weaponID = 10
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB3_ID1 and monster.monster_id <= CopyDefine.WUSHUANG_JOB3_ID2 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB3_ID1) * 10
        bone = 5
        weaponID = 8
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB3_ID3 and monster.monster_id <= CopyDefine.WUSHUANG_JOB3_ID4 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB3_ID3) * 10
        bone = 5
        weaponID = 8
        horse = 1004
    elseif monster.monster_id >= CopyDefine.WUSHUANG_JOB3_ID5 and monster.monster_id <= CopyDefine.WUSHUANG_JOB3_ID6 then
        body = 21 + (monster.monster_id - CopyDefine.WUSHUANG_JOB3_ID5) * 10
        bone = 5
        weaponID = 8
        horse = 1004
    end
        
    return body,weaponID,weaponEffect,pifengID,horse, bone,weaponID2,0,0,0,bodyColor
end



local tb = {"mainUtility", "mustUtility", "appendUtility1", "appendUtility2", "appendUtility3"}
function onSkill(monster, x, y,skillID)
    local config = SkillConfig[skillID]
    if config.actionID[1]~=-1 then
        if Timer.last_exe_time.walk --[[ and Timer.now - Timer.last_exe_time.walk > 0 ]] then
            if monster.path_len ~= 0 then
                Obj.stop(monster)
                monster.had_stop = 1
            elseif not monster.had_stop then -- 如果没有广播STOP_MOVE,强制同步一把
                local msgRet = Msg.gc.GC_STOP_MOVE
                msgRet.dir = monster.dir or 4
                msgRet.obj_id = monster.id
                msgRet.x = monster.x
                msgRet.y = monster.y
                Obj.sendArea(msgRet, monster.scene_id, monster.x, monster.y, monster.fd)
                monster.had_stop = 1
            end

            -- print("Monster Onskill stop x:", monster.x, " y:", monster.y)
        else
            Obj.resetPathParam(monster)
            -- print("Monster Onskill reset x", monster.x, " y:", monster.y)
            monster.had_stop = 1
        end
    end
    local qianyao_time = config.qianyao_sec>0 and config.qianyao_sec*1000 or config.actionDelay
    if not monster.wake_up_time or monster.wake_up_time < qianyao_time + Timer.now then
        monster.wake_up_time = qianyao_time + Timer.now
    end
    for _, v in ipairs(tb) do
        local cf = Utility[config[v]]
        if cf and (cf.utility == "rush" or cf.utility == "jumpTo") then
            monster.wake_up_time = 1000 + Timer.now
            break
        end
    end
end

function getValue(monster, key)
    return ExcelMonsterConf.monster[monster.monster_id][key]
end

function getValueByMonsterType(monster, key)
    local monster_type = ExcelMonsterConf.monster[monster.monster_id].monster_type
    return ExcelMonsterConf.monster_type[monster_type][key]
end

function getMonsterCamps(monsterID)
    local nCamps = ExcelMonsterConf.monster[monsterID].camps
    if nCamps then
        return CAMPS[nCamps] and CAMPS[nCamps] + 0 or 0
    end
    return 0
end

function sendMonsterCorpseList(scene_id, human)
    if MONSTERCORPSE_LIST[scene_id] then
        local nMonsterCorpseMsg = Msg.gc.GC_MONSTERCORPSE_REWARDCONFIG
        for k, v in pairs(MONSTERCORPSE_LIST[scene_id]) do
            local nObj = Obj.objs[k]
            if nObj and nObj.obj_type == Obj.TYPE_MONSTER then
                local nMonsterConfig = ExcelMonsterConf.monster[nObj.monster_id]
                if nMonsterConfig.canCorpseReward == 1 and nObj.dieTime and nMonsterConfig.die_remain * 1000 >= Timer.now - nObj.dieTime then
                    local nSend = true
                    local nMonsterCorpseData = nil
                    if human then
                        nMonsterCorpseData = v[human._id]
                        local nMaxRewardTimes = #nMonsterConfig.corpseRewardData
                        if nMaxRewardTimes <= 0 or (nMonsterCorpseData and nMonsterCorpseData.curtimes >= nMaxRewardTimes) then
                            nSend = false
                        end
                    end
                    if nSend then
                        nMonsterCorpseMsg.type = 0
                        nMonsterCorpseMsg.monster_id = k
                        nMonsterCorpseMsg.curtimes = 0
                        nMonsterCorpseMsg.timeslist[0] = 0
                        for kk, vv in pairs(nMonsterConfig.corpseRewardData) do
                            nMonsterCorpseMsg.timeslist[0] = nMonsterCorpseMsg.timeslist[0] + 1
                            local nCorpseData = nMonsterCorpseMsg.timeslist[nMonsterCorpseMsg.timeslist[0]]
                            nCorpseData.type = vv[1]
                            nCorpseData.consume = vv[2]
                            nCorpseData.reward[0] = 0
                            for nRewardIndex, nRewardData in ipairs(vv[3]) do
                                nCorpseData.reward[0] = nCorpseData.reward[0] + 1
                                local nItemData = nCorpseData.reward[nCorpseData.reward[0]]
                                local grid = get_grid(nRewardData[1], nRewardData[2], nRewardData[3], nRewardData[4] or 0)
                                Grid.makeItem(grid, nItemData)
                            end
                        end

                        if human then
                            nMonsterCorpseMsg.curtimes = nMonsterCorpseData and nMonsterCorpseData.curtimes or 0 
                            Msg.send(nMonsterCorpseMsg, human.fd)
                        else
                            Obj.sendScene(nMonsterCorpseMsg, scene_id)
                        end
                    end
                end
            end
        end
    end
end

function get_grid(itemID, itemNum, itemColor, itemBind)
    local grid = Grid.create(nil, itemID, itemNum, itemBind, ItemDefine.qualityOut[itemColor])
    return grid
end
